/*
 * X11 三角形渲染测试 - 软件渲染版本
 * 使用纯C语言和X11实现
 * 
 * 编译命令：
 * gcc -o x11_triangle_render x11_triangle_render.c -lX11 -lm
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include <sys/time.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>


// 窗口尺寸
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600

// 颜色结构
typedef struct {
    unsigned char r, g, b;
} Color;

// 点结构
typedef struct {
    float x, y;
} Point;

// X11上下文结构
typedef struct {
    Display *display;
    Window window;
    GC gc;
    Pixmap pixmap;
    XImage *image;
    int screen;
    Visual *visual;
    unsigned char *framebuffer;
} RenderContext;

// 三角形顶点数据
static const Point triangle_vertices[] = {
    { 0.0f,  0.5f},  // 顶部
    {-0.5f, -0.5f},  // 左下
    { 0.5f, -0.5f}   // 右下
};

// 三角形颜色
static const Color triangle_colors[] = {
    {255, 0, 0},    // 红色
    {0, 255, 0},    // 绿色
    {0, 0, 255}     // 蓝色
};

// 性能统计
typedef struct {
    double frame_time;
    double render_time;
    double present_time;
    double total_frame_time;
    int frame_count;
    struct timeval start_time;
    struct timeval frame_start_time;
    double min_frame_time;
    double max_frame_time;
    double avg_frame_time;
} PerformanceStats;

// 获取时间差（毫秒）
double get_time_diff(struct timeval start, struct timeval end) {
    return (end.tv_sec - start.tv_sec) * 1000.0 + 
           (end.tv_usec - start.tv_usec) / 1000.0;
}

// 设置像素颜色
void set_pixel(RenderContext *ctx, int x, int y, Color color) {
    if (x >= 0 && x < WINDOW_WIDTH && y >= 0 && y < WINDOW_HEIGHT) {
        int index = (y * WINDOW_WIDTH + x) * 4;
        ctx->framebuffer[index + 0] = color.b;  // Blue
        ctx->framebuffer[index + 1] = color.g;  // Green  
        ctx->framebuffer[index + 2] = color.r;  // Red
        ctx->framebuffer[index + 3] = 255;      // Alpha
    }
}

// 清屏
void clear_screen(RenderContext *ctx, Color color) {
    for (int y = 0; y < WINDOW_HEIGHT; y++) {
        for (int x = 0; x < WINDOW_WIDTH; x++) {
            set_pixel(ctx, x, y, color);
        }
    }
}

// 线性插值
Color lerp_color(Color c1, Color c2, float t) {
    Color result;
    result.r = (unsigned char)(c1.r + t * (c2.r - c1.r));
    result.g = (unsigned char)(c1.g + t * (c2.g - c1.g));
    result.b = (unsigned char)(c1.b + t * (c2.b - c1.b));
    return result;
}

// 画线（Bresenham算法）
void draw_line(RenderContext *ctx, Point p1, Point p2, Color c1, Color c2) {
    int x1 = (int)((p1.x + 1.0f) * WINDOW_WIDTH / 2);
    int y1 = (int)((1.0f - p1.y) * WINDOW_HEIGHT / 2);
    int x2 = (int)((p2.x + 1.0f) * WINDOW_WIDTH / 2);
    int y2 = (int)((1.0f - p2.y) * WINDOW_HEIGHT / 2);
    
    int dx = abs(x2 - x1);
    int dy = abs(y2 - y1);
    int sx = x1 < x2 ? 1 : -1;
    int sy = y1 < y2 ? 1 : -1;
    int err = dx - dy;
    
    int x = x1, y = y1;
    float total_dist = sqrt(dx*dx + dy*dy);
    
    while (1) {
        float dist = sqrt((x-x1)*(x-x1) + (y-y1)*(y-y1));
        float t = total_dist > 0 ? dist / total_dist : 0;
        Color color = lerp_color(c1, c2, t);
        set_pixel(ctx, x, y, color);
        
        if (x == x2 && y == y2) break;
        
        int e2 = 2 * err;
        if (e2 > -dy) {
            err -= dy;
            x += sx;
        }
        if (e2 < dx) {
            err += dx;
            y += sy;
        }
    }
}

// 填充三角形（扫描线算法）
void fill_triangle(RenderContext *ctx, Point p1, Point p2, Point p3, 
                   Color c1, Color c2, Color c3) {
    // 转换为屏幕坐标
    int x1 = (int)((p1.x + 1.0f) * WINDOW_WIDTH / 2);
    int y1 = (int)((1.0f - p1.y) * WINDOW_HEIGHT / 2);
    int x2 = (int)((p2.x + 1.0f) * WINDOW_WIDTH / 2);
    int y2 = (int)((1.0f - p2.y) * WINDOW_HEIGHT / 2);
    int x3 = (int)((p3.x + 1.0f) * WINDOW_WIDTH / 2);
    int y3 = (int)((1.0f - p3.y) * WINDOW_HEIGHT / 2);
    
    // 找到边界
    int min_y = y1 < y2 ? (y1 < y3 ? y1 : y3) : (y2 < y3 ? y2 : y3);
    int max_y = y1 > y2 ? (y1 > y3 ? y1 : y3) : (y2 > y3 ? y2 : y3);
    
    for (int y = min_y; y <= max_y; y++) {
        // 使用重心坐标进行颜色插值
        for (int x = 0; x < WINDOW_WIDTH; x++) {
            // 计算重心坐标
            float denom = (float)((y2 - y3)*(x1 - x3) + (x3 - x2)*(y1 - y3));
            if (fabs(denom) < 0.001f) continue;
            
            float a = (float)((y2 - y3)*(x - x3) + (x3 - x2)*(y - y3)) / denom;
            float b = (float)((y3 - y1)*(x - x3) + (x1 - x3)*(y - y3)) / denom;
            float c = 1.0f - a - b;
            
            // 检查点是否在三角形内
            if (a >= 0 && b >= 0 && c >= 0) {
                // 颜色插值
                Color color;
                color.r = (unsigned char)(a * c1.r + b * c2.r + c * c3.r);
                color.g = (unsigned char)(a * c1.g + b * c2.g + c * c3.g);
                color.b = (unsigned char)(a * c1.b + b * c2.b + c * c3.b);
                set_pixel(ctx, x, y, color);
            }
        }
    }
}

// 初始化渲染上下文
int init_render_context(RenderContext *ctx) {
    // 打开X11显示
    ctx->display = XOpenDisplay(NULL);
    if (!ctx->display) {
        fprintf(stderr, "错误: 无法打开X11显示\n");
        return 0;
    }
    
    ctx->screen = DefaultScreen(ctx->display);
    ctx->visual = DefaultVisual(ctx->display, ctx->screen);
    
    // 创建窗口
    ctx->window = XCreateSimpleWindow(ctx->display,
                                     RootWindow(ctx->display, ctx->screen),
                                     0, 0, WINDOW_WIDTH, WINDOW_HEIGHT,
                                     1, BlackPixel(ctx->display, ctx->screen),
                                     WhitePixel(ctx->display, ctx->screen));
    
    // 设置窗口标题
    XStoreName(ctx->display, ctx->window, "X11 三角形渲染测试 - 软件渲染");
    
    // 选择事件
    XSelectInput(ctx->display, ctx->window, 
                 ExposureMask | KeyPressMask | StructureNotifyMask);
    
    // 创建图形上下文
    ctx->gc = XCreateGC(ctx->display, ctx->window, 0, NULL);
    
    // 创建像素缓冲区
    ctx->pixmap = XCreatePixmap(ctx->display, ctx->window, 
                               WINDOW_WIDTH, WINDOW_HEIGHT,
                               DefaultDepth(ctx->display, ctx->screen));
    
    // 分配帧缓冲区
    ctx->framebuffer = malloc(WINDOW_WIDTH * WINDOW_HEIGHT * 4);
    if (!ctx->framebuffer) {
        fprintf(stderr, "错误: 无法分配帧缓冲区\n");
        return 0;
    }
    
    // 创建XImage
    ctx->image = XCreateImage(ctx->display, ctx->visual,
                             DefaultDepth(ctx->display, ctx->screen),
                             ZPixmap, 0, (char*)ctx->framebuffer,
                             WINDOW_WIDTH, WINDOW_HEIGHT, 32, 0);
    
    if (!ctx->image) {
        fprintf(stderr, "错误: 无法创建XImage\n");
        free(ctx->framebuffer);
        return 0;
    }
    
    // 显示窗口
    XMapWindow(ctx->display, ctx->window);
    XFlush(ctx->display);
    
    return 1;
}

// 清理渲染上下文
void cleanup_render_context(RenderContext *ctx) {
    if (ctx->image) {
        XDestroyImage(ctx->image);
    }
    if (ctx->framebuffer) {
        free(ctx->framebuffer);
    }
    if (ctx->pixmap) {
        XFreePixmap(ctx->display, ctx->pixmap);
    }
    if (ctx->gc) {
        XFreeGC(ctx->display, ctx->gc);
    }
    if (ctx->window) {
        XDestroyWindow(ctx->display, ctx->window);
    }
    if (ctx->display) {
        XCloseDisplay(ctx->display);
    }
}

// 打印GPU信息（模拟）
void print_gpu_info() {
    printf("\n=== 系统图形信息 ===\n");
    printf("渲染方式: 软件渲染 (CPU)\n");
    printf("图形库: X11 + 自定义软件光栅化\n");
    printf("窗口尺寸: %dx%d\n", WINDOW_WIDTH, WINDOW_HEIGHT);
    printf("颜色深度: 32位 RGBA\n");
    printf("三角形算法: 重心坐标插值\n");
    printf("==================\n\n");
}

// 渲染三角形
void render_triangle(RenderContext *ctx, PerformanceStats *stats) {
    struct timeval render_start, render_end;
    gettimeofday(&render_start, NULL);
    
    // 清屏（深蓝色背景）
    Color bg_color = {26, 26, 77}; // RGB(26, 26, 77)
    clear_screen(ctx, bg_color);
    
    // 渲染填充三角形
    fill_triangle(ctx, triangle_vertices[0], triangle_vertices[1], triangle_vertices[2],
                  triangle_colors[0], triangle_colors[1], triangle_colors[2]);
    
    // 可选：绘制三角形边框
    Color white = {255, 255, 255};
    draw_line(ctx, triangle_vertices[0], triangle_vertices[1], white, white);
    draw_line(ctx, triangle_vertices[1], triangle_vertices[2], white, white);
    draw_line(ctx, triangle_vertices[2], triangle_vertices[0], white, white);
    
    gettimeofday(&render_end, NULL);
    stats->render_time = get_time_diff(render_start, render_end);
}

// 显示渲染结果
void present_frame(RenderContext *ctx, PerformanceStats *stats) {
    struct timeval present_start, present_end;
    gettimeofday(&present_start, NULL);
    
    XPutImage(ctx->display, ctx->window, ctx->gc, ctx->image,
              0, 0, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT);
    XFlush(ctx->display);
    
    gettimeofday(&present_end, NULL);
    stats->present_time = get_time_diff(present_start, present_end);
}

// 更新性能统计
void update_performance_stats(PerformanceStats *stats) {
    struct timeval frame_end;
    gettimeofday(&frame_end, NULL);
    
    // 计算当前帧的总时间
    stats->total_frame_time = get_time_diff(stats->frame_start_time, frame_end);
    
    // 更新最小、最大帧时间
    if (stats->frame_count == 0) {
        stats->min_frame_time = stats->total_frame_time;
        stats->max_frame_time = stats->total_frame_time;
        stats->avg_frame_time = stats->total_frame_time;
    } else {
        if (stats->total_frame_time < stats->min_frame_time) {
            stats->min_frame_time = stats->total_frame_time;
        }
        if (stats->total_frame_time > stats->max_frame_time) {
            stats->max_frame_time = stats->total_frame_time;
        }
        // 计算平均帧时间
        stats->avg_frame_time = (stats->avg_frame_time * stats->frame_count + stats->total_frame_time) / (stats->frame_count + 1);
    }
    
    stats->frame_count++;
    
    struct timeval current_time;
    gettimeofday(&current_time, NULL);
    stats->frame_time = get_time_diff(stats->start_time, current_time);
    
    // 每秒输出一次统计信息
    if (stats->frame_time >= 1000.0) {
        double fps = stats->frame_count / (stats->frame_time / 1000.0);
        printf("\n=== 性能统计 ===\n");
        printf("FPS: %.2f\n", fps);
        printf("当前帧时间: %.3f ms\n", stats->total_frame_time);
        printf("渲染时间: %.3f ms\n", stats->render_time);
        printf("显示时间: %.3f ms\n", stats->present_time);
        printf("最小帧时间: %.3f ms\n", stats->min_frame_time);
        printf("最大帧时间: %.3f ms\n", stats->max_frame_time);
        printf("平均帧时间: %.3f ms\n", stats->avg_frame_time);
        printf("总帧数: %d\n", stats->frame_count);
        printf("===============\n\n");
        
        // 重置统计
        stats->frame_count = 0;
        gettimeofday(&stats->start_time, NULL);
        stats->min_frame_time = 0;
        stats->max_frame_time = 0;
        stats->avg_frame_time = 0;
    }
}

// 处理X11事件
int handle_events(RenderContext *ctx) {
    XEvent event;
    
    while (XPending(ctx->display)) {
        XNextEvent(ctx->display, &event);
        
        switch (event.type) {
            case KeyPress: {
                KeySym key = XLookupKeysym(&event.xkey, 0);
                if (key == XK_Escape || key == XK_q || key == XK_Q) {
                    return 0; // 退出
                }
                break;
            }
            case ConfigureNotify:
                // 窗口大小改变（暂不处理）
                break;
            case ClientMessage:
                return 0; // 窗口关闭
            case Expose:
                // 需要重绘（在主循环中处理）
                break;
        }
    }
    return 1; // 继续运行
}

// 主函数
int main(int argc, char *argv[]) {
    printf("X11 三角形渲染测试启动...\n");
    printf("使用软件渲染引擎（不依赖外部OpenGL库）\n");
    
    RenderContext ctx = {0};
    PerformanceStats stats = {0};
    
    // 初始化渲染上下文
    if (!init_render_context(&ctx)) {
        fprintf(stderr, "错误: 渲染上下文初始化失败\n");
        return 1;
    }
    
    printf("渲染上下文创建成功\n");
    
    // 打印系统信息
    print_gpu_info();
    
    // 初始化性能统计
    gettimeofday(&stats.start_time, NULL);
    
    printf("开始渲染循环... (按 ESC 或 Q 退出)\n");
    
    // 主渲染循环
    while (1) {
        // 开始帧时间统计
        gettimeofday(&stats.frame_start_time, NULL);
        
        // 处理事件
        if (!handle_events(&ctx)) {
            break;
        }
        
        // 渲染三角形
        render_triangle(&ctx, &stats);
        
        // 显示帧
        present_frame(&ctx, &stats);
        
        // 更新性能统计
        update_performance_stats(&stats);
        
        // 控制帧率
        usleep(16666); // ~60 FPS
    }
    
    printf("\n程序退出，清理资源...\n");
    
    // 清理资源
    cleanup_render_context(&ctx);
    
    printf("X11 三角形渲染测试结束\n");
    return 0;
}